﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Xml.Linq;

namespace YArchitech.MEP
{
	public class HYDuctSpecifications : SortedSet<HYDuctSpecification>
	{
		public HYDuctSpecifications()
		{
		}

		public HYDuctSpecifications(IEnumerable<HYDuctSpecification> source) : base(source)
		{
		}

		public void GetAllWidth(out SortedSet<int> widths)
		{
			widths = new SortedSet<int>();
			foreach (HYDuctSpecification hyductSpecification in this)
			{
				widths.Add((int)hyductSpecification.Size.Width);
			}
		}

		public void GetAllHeight(out SortedSet<int> heights)
		{
			heights = new SortedSet<int>();
			foreach (HYDuctSpecification hyductSpecification in this)
			{
				heights.Add((int)hyductSpecification.Size.Height);
			}
		}

		public HYDuctSpecifications GetMatchSpecificationsByFactor(double rectFactor = 4.0, double rectFactorDeviation = 1.0)
		{
			IOrderedEnumerable<HYDuctSpecification> orderedEnumerable = from sec in this
			where Math.Abs(sec.Size.Factor - rectFactor) < 0.5 + rectFactorDeviation
			orderby sec descending
			select sec;
			if (orderedEnumerable == null)
			{
				return null;
			}
			return new HYDuctSpecifications(orderedEnumerable);
		}

		public HYDuctSpecifications GetMatchSpecificationsByWidth(HYRange widthRange)
		{
			return new HYDuctSpecifications(from sec in this
			where widthRange.Test(sec.Size.Width) == 0
			select sec);
		}

		public HYDuctSpecifications GetMatchSpecificationsByHeight(HYRange heightRange)
		{
			return new HYDuctSpecifications(from sec in this
			where heightRange.Test(sec.Size.Height) == 0
			select sec);
		}

		public HYDuctSpecification SelectSectionByVelocity(double flow, double designVelocity)
		{
			double num = double.MaxValue;
			HYDuctSpecification result = base.Max;
			foreach (HYDuctSpecification hyductSpecification in this)
			{
				double num2 = Math.Abs(hyductSpecification.Size.GetVelocity(flow) - designVelocity);
				if (num > num2)
				{
					num = num2;
					result = hyductSpecification;
				}
			}
			return result;
		}

		public void Load(IDataReader reader)
		{
			this.Clear();
			while (reader.Read())
			{
				HYDuctSpecification item = HYDuctSpecification.FromDataReader(reader);
				if (item.Size.IsValid)
				{
					base.Add(item);
				}
			}
		}

		public void WriteXml(XElement xe)
		{
			foreach (HYDuctSpecification hyductSpecification in this)
			{
				XElement xelement = new XElement("Specification");
				hyductSpecification.WriteXml(xelement);
				xe.Add(xelement);
			}
		}

		public void ReadXml(XElement xe)
		{
			this.Clear();
			foreach (XElement xe2 in xe.Elements("Specification"))
			{
				HYDuctSpecification item = default(HYDuctSpecification);
				item.ReadXml(xe2);
				base.Add(item);
			}
		}

		public bool FilterRectangularSpecs(HYDuctSystemOption Option, out IEnumerable<HYDuctSpecification> mainSize, out IEnumerable<HYDuctSpecification> sideSize)
		{
			IEnumerable<HYDuctSpecification> enumerable = from sec in this
			where sec.Size.Shape == HYTubeShape.Rectangular
			select sec;
			if (enumerable == null || enumerable.Count<HYDuctSpecification>() == 0)
			{
				throw new Exception("没有矩形风管数据，请首先设置风管管径！");
			}
			IEnumerable<HYDuctSpecification> enumerable2;
			if (Option.RectRactorEnable)
			{
				enumerable2 = this.GetMatchByFactor(enumerable, Option.RectFactor, Option.RectFactorDeviation);
			}
			else
			{
				enumerable2 = enumerable;
			}
			if (enumerable2 == null || enumerable2.Count<HYDuctSpecification>() == 0)
			{
				throw new Exception("宽高比设置不合理，过滤不到管径。请重新设置。");
			}
			mainSize = enumerable2;
			if (Option.MainRangeEnable)
			{
				mainSize = this.GetMatchByHeight(enumerable2, Option.MainRange);
			}
			if (mainSize == null || mainSize.Count<HYDuctSpecification>() == 0)
			{
				throw new Exception("主管高度范围设置不合理，过滤不到管径，请重新设置。");
			}
			sideSize = enumerable2;
			if (Option.SideRangeEnable)
			{
				sideSize = this.GetMatchByHeight(enumerable2, Option.SideRange);
			}
			if (sideSize == null || sideSize.Count<HYDuctSpecification>() == 0)
			{
				throw new Exception("支管高度范围设置不合理，过滤不到管径，请重新设置。");
			}
			return true;
		}

		private IEnumerable<HYDuctSpecification> GetMatchByFactor(IEnumerable<HYDuctSpecification> source, double factor, double factorDeviation)
		{
			return from sz in source
			where Math.Abs(sz.Size.Factor - factor) < factorDeviation + 0.5
			orderby sz.Size descending
			select sz;
		}

		private IEnumerable<HYDuctSpecification> GetMatchByHeight(IEnumerable<HYDuctSpecification> source, HYRange range)
		{
			return from sz in source
			where range.Test(sz.Size.Height) == 0
			orderby sz.Size descending
			select sz;
		}
	}
}
